home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / debugtx.arc / XBIOS.8 < prev    next >
Encoding:
Text File  |  1991-08-11  |  18.8 KB  |  539 lines

  1. ;---------------
  2. ;  XBIOS test driver for BIOS.8
  3. ;---------------
  4.  
  5. ; Copyright (C)1987 Eric Isaacson.  All rights reserved.  Permission to
  6. ; copy and use this module is granted ONLY for machines registered for both
  7. ; the A86 assembler and the D86 debugger.
  8.  
  9. ; XBIOS is a program that exercises the BIOS.8 module.    I am providing it
  10. ; to assist those who wish to assist me in porting my D86 debugger to
  11. ; machines with non-IBM-compatible BIOSes.
  12.  
  13. ; You use this source module as follows:
  14. ;
  15. ;  1. Modify the module BIOS.8 to accommodate your specific machine.  You
  16. ;     should NOT need to modify this module, except possibly to add a
  17. ;     new HELP-key name just before the declcaration HELP_HELP below.
  18. ;
  19. ;  2. Assemble both modules with the command  A86 XBIOS.8 BIOS.8
  20. ;     (Command is provided as MAKX.BAT in this package; just type MAKX.)
  21. ;
  22. ;  3. Run the resulting program XBIOS.COM.  The program will run tests
  23. ;     of the BIOS function calls, and tell you about them.  If everything
  24. ;     looks good, then your BIOS.8 probably works.
  25. ;
  26. ;  4. The XBIOS program ends with an interactive mode, displaying keystrokes.
  27. ;     Please try every key on your keyboard, both with and without any
  28. ;     shift-style keys (ALT, SHIFT, CTRL, SECOND, etc.).  Write down the
  29. ;     codes that result.
  30. ;
  31. ;  5. Send me the codes you wrote down, together with your new BIOS.8.  I'll
  32. ;     incorporate it into D86.    Thanks!
  33.  
  34.  
  35.  
  36. ; This is a "quick-and-dirty" program.  It does not meet my standards for
  37. ; professionally-documented source code (no procedure-level comments).
  38.  
  39.  
  40. JMP MAIN
  41.  
  42. ALTF10_HELP:        ; HELP-key name for the IBM-PC
  43.   DB 'Alt-F10',0
  44. F11_HELP:        ; HELP-key name for the TI-PC
  45.   DB 'F11',0
  46. PF5_HELP:
  47.   DB 'Ctrl-PF5',0
  48. ; If your machine uses a different HELP-KEY, declare its name above this line.
  49.  
  50. HELP_HELP:
  51.   DB 'HELP',0
  52.  
  53.  
  54. ENABLE_PORT  DW ?      ; BIOS specific, used by Wang for a port number
  55. V_FLAG         DB ?      ; debugger variable consulted by IBM BIOS_INIT
  56. WAVY_COUNT   DB ?      ; count of how many wavy messages have been output
  57.  
  58. ; DWB causes the initialization of alternating words and bytes
  59.  
  60. DWB MACRO #RX1L
  61.   DW #X
  62.   DB #AX
  63. #E2#EM
  64.  
  65. SKIP2 MACRO    ; skip over the following 2 opcode bytes
  66.   DB 03D       ; CMP AX,iw opcode will do the job
  67. #EM
  68.  
  69.  
  70. SCREEN_P EQU 08000  ; screen buffer is at 08000
  71.  
  72. ; The following are convenient prefix-abbreviations for returned key-codes.
  73.  
  74. CTRL EQU -040       ; e.g. CTRL'A'  -- WARNING CTRL'a' will be wrong!!
  75. FUNC EQU 59+111     ; e.g. FUNC 1 for the F1 function key
  76. SHIFT_F EQU 84+111  ; e.g. SHIFT_F 3 for the shifted F3 key
  77. CTRL_F EQU 94+111   ; e.g. CTRL_F 10 for the control-F10 key
  78. ALT_F EQU 104+111   ; e.g. ALT_F 4 for the Alt-F4 key
  79. ALT_N EQU 120+111   ; e.g. ALT_N 5 for the Alt-5 key
  80.  
  81. BIOS_CALLS:              ; pointers to BIOS-specific action routines
  82.   VID_COPY    DW MONO_COPY  ; video copy
  83.   VID_ATTR    DW IBM_ATTR   ; set attribute at DI to AL
  84.   VID_FIX    DW IBM_FIX    ; fix video screen
  85.   BIOS_BELL    DW IBM_BELL   ; ring bell
  86.   BIOS_KEY    DW IBM_KEY    ; fetch a keystroke
  87.   BIOS_SAVE     DW IBM_SAVE   ; save user's BIOS state (Sanyo only)
  88.   BIOS_RESTORE    DW IBM_RESTORE; restore the saved BIOS state (Sanyo only)
  89.   VIDEO_SEG    DW ?          ; pointer to physical video display segment
  90.   ATTR_BYTES    DW          ; hardware-dependent video codes
  91.    NORM_ATTR    DB 7          ; code for normal video display
  92.    REV_ATTR    DB 070          ; code for reversed-video display
  93. N_BIOS_CALLS EQU ($-BIOS_CALLS)/2
  94.  
  95. BIOS_INIT   DW IBM_CONFIG
  96.  
  97.  
  98. ; CTRL_JUMPS defines the single-key commands recognized by the debugger.  Each
  99. ;   DW below is an address to be jumped to whenever the following DB byte is
  100. ;   taken as a single-key input by the debugger command processor.
  101.  
  102. CTRL EQU -040
  103.  
  104. CTRL_JUMPS:
  105.   DWB  F1_MSG,        FUNC 1
  106.   DWB  F2_MSG,        FUNC 2
  107.   DWB  F3_MSG,        FUNC 3
  108.   DWB  F4_MSG,        FUNC 4
  109.   DWB  F5_MSG,        FUNC 5
  110.   DWB  F6_MSG,        FUNC 6
  111.   DWB  F7_MSG,        FUNC 7
  112. N_FUNCS EQU ($-CTRL_JUMPS)/3
  113.  
  114. L1:                ; control-key functions start here
  115.   DWB  DOWN_MSG,    80+112
  116.   DWB  PGDN_MSG,    81+112
  117.   DWB  UP_MSG,        72+112
  118.   DWB  HOME_MSG,    71+112
  119.   DWB  SHF7_MSG, SHIFT_F 7
  120.   DWB  ALTF9_MSG,  ALT_F 9
  121. N_CONTROL_KEYS EQU ($-L1)/3
  122.  
  123.          DW F10_MSG
  124. SWITCH_KEY   DB FUNC 10   ; key code for FUNC 10 (switch screens)
  125.  
  126.          DW HELP_HELP
  127. HELP_KEY     DB ALT_F 10  ; key code for the debugger's HELP key
  128.  
  129.   DWB  0,        0FF     ; terminator for this table
  130.  
  131.  
  132.  
  133.  
  134.  
  135. MAIN:
  136.   CALL SET_MACHINE    ; set SUBDIR_CHAR and BIOS_INIT
  137.   CALL BIOS_INIT    ; initialize our specific BIOS
  138.   MOV DS,ES,SS        ; restore segment registers
  139.   CALL TEST_INIT    ; display the settings produced, prompt for key
  140.   CALL TEST_KEY_BELL    ; test the simple key input and bell functions
  141.   CALL TEST_VIDEO    ; test some simple video displays
  142.   CALL TEST_KEY_CODES    ; enter the interactive key-code display loop
  143.   MOV AX,04C00        ; MS-DOS codes for successful program exit
  144.   INT 33        ; exit back to the operating system
  145.  
  146.  
  147. FIRST_TESTING:
  148.   DB 'Survived BIOS_INIT.',0D,0A
  149.   DB 'Subdirectory character is set to "'
  150. SUBDIR_CHAR  DB '\'
  151.   DB '".',0D,0A
  152.   DB 'Video memory is at segment register value '
  153. VIDEO_DISPLAY:
  154.   DB 'xxxx.',0D,0A
  155.   DB 'The normal attribute byte is '
  156. NORM_DISP:
  157.   DB 'xx.',0D,0A
  158.   DB 'The reverse attribute byte is '
  159. REV_DISP:
  160.   DB 'xx.',0D,0A
  161.   DB 'The HELP key is labelled ',0
  162.  
  163. HELP_MSG     DW ALTF10_HELP
  164.  
  165. POST_HELP:
  166.   DB '.',0D,0A
  167.   DB 'Is this right?',0D,0A,0D,0A
  168.   DB 'First testing BIOS key input and bell-ringing.',0D,0A,0
  169.  
  170. TEST_INIT:        ; make initial display of BIOS variables
  171.   MOV BX,VIDEO_SEG    ; fetch the video segment register value
  172.   MOV DI,VIDEO_DISPLAY    ; point to it position in the display message
  173.   MOV AL,BH        ; fetch the high byte of the value
  174.   CALL HEX_AL        ; output the high byte
  175.   MOV AL,BL        ; fetch the low byte of the value
  176.   CALL HEX_AL        ; output the low byte
  177.   MOV DI,NORM_DISP    ; point to NORM_ATTR value in message
  178.   MOV AL,NORM_ATTR    ; fetch the value
  179.   CALL HEX_AL        ; put the hex value into the message
  180.   MOV DI,REV_DISP    ; point to REV_ATTR value in message
  181.   MOV AL,REV_ATTR    ; fetch the value
  182.   CALL HEX_AL        ; put the hex value into the message
  183.   MOV SI,FIRST_TESTING    ; point to the first message
  184.   CALL MESSAGE        ; output the message
  185.   MOV SI,HELP_MSG    ; point to the name of the HELP key
  186.   CALL MESSAGE        ; output the name
  187.   MOV SI,POST_HELP    ; point to the message after the HELP name
  188.   JMP MESSAGE        ; output the message
  189.  
  190.  
  191.  
  192. VID_TEST_MSG:
  193.   DB 'Now we''ll output directly to video memory.',0D,0A
  194.   DB 'Type any two keys--',0D,0A
  195.   DB 'The screen will go blank after the first keystroke.',0D,0A,0
  196.  
  197. ALPHABET_MSG:
  198.   DB 'Now letters A to X go down the left.',0
  199. H_MSG:
  200.   DB 'Reverse video on the H.',0
  201. AFTER_M_MSG:
  202.   DB 'Reverse video 2 beyond the M.',0
  203.  
  204. H_SPOT EQU  ('H'-'A') * 160
  205. AFTER_M_SPOT EQU ('M'-'A') * 160 + 4
  206.  
  207. TEST_VIDEO:
  208.   MOV SI,VID_TEST_MSG   ; point to the "Now testing video" message
  209.   CALL MESSAGE        ; output the message
  210.   CALL KEY_ONLY     ; take a keystroke
  211.   CALL FIRST_FILL    ; blank the screen
  212.   CALL GET_KEY        ; take another keystroke
  213.   CALL ALPHA_LINES    ; put out the alphabet along the side
  214.   MOV SI,ALPHABET_MSG    ; point to message telling about it
  215.   CALL TOP_LINE     ; output the message
  216.   CALL REFRESH        ; send it all to the video
  217.   CALL GET_KEY        ; take another key
  218.   MOV SI,H_MSG        ; point to cursor-on-H message
  219.   CALL TOP_LINE     ; output the message
  220.   CALL REFRESH        ; refresh the video memory
  221.   MOV ES,VIDEO_SEG    ; point to the video segment
  222.   MOV DI,H_SPOT         ; point to "H" character within that segment
  223.   MOV AL,REV_ATTR    ; load the reverse-attribute byte
  224.   CALL VID_ATTR     ; output the byte to the video segment
  225.   MOV ES,SS        ; restore ES
  226.   CALL GET_KEY        ; take another keystroke
  227.   MOV SI,AFTER_M_MSG    ; point to cursor-after-M message
  228.   CALL TOP_LINE     ; output the message
  229.   CALL REFRESH        ; refresh the video memory
  230.   MOV ES,VIDEO_SEG    ; point to the video segment
  231.   MOV DI,H_SPOT     ; point to the previous cursor position in segment
  232.   MOV AL,NORM_ATTR    ; load normal attribute
  233.   CALL VID_ATTR     ; cancel the previous cursor output
  234.   MOV DI,AFTER_M_SPOT    ; point to the new cursor position
  235.   MOV AL,REV_ATTR    ; load reverse-attribute byte
  236.   CALL VID_ATTR     ; output the new cursor
  237.   MOV ES,SS        ; restore ES
  238. GET_KEY:
  239.   CALL BIOS_RESTORE
  240.   CALL BIOS_KEY
  241.   RET
  242.  
  243.  
  244. PLEASE_TYPE:
  245.   DB 'Please type any key.',0D,0A,0
  246. KEY_ONLY_MSG:
  247.   DB 'The BIOS returned hex code '
  248. KEY_ONLY_HEXCODE:
  249.   DB 'xx.',0D,0A,0
  250.  
  251. KEY_ONLY:
  252.   MOV SI,PLEASE_TYPE      ; point to "Please type any key"
  253.   CALL MESSAGE            ; output "Please type any key"
  254.   MOV DI,KEY_ONLY_HEXCODE ; output goes to the key-value report
  255.   MOV SI,KEY_ONLY_MSG      ; point to start of key-value report
  256.   CALL GET_KEY          ; fetch a keystroke from the BIOS
  257.   CALL HEX_AL          ; place the hex code into the message
  258. MESSAGE:          ; output null-terminated SI-message to standard out
  259.   PUSH BX,CX,DX       ; save registers across call
  260.   MOV DX,SI          ; MS-DOS wants the message pointer in DX
  261. L1:              ; loop here to scan for the terminator
  262.   LODSB           ; fetch a string byte
  263.   TEST AL          ; is it the zero terminator?
  264.   JNZ L1          ; loop if not
  265.   LEA CX,[SI-1]       ; point CX to the terminator byte
  266.   SUB CX,DX          ; compute the number of characters in the message
  267.   MOV AH,040          ; MS-DOS function number for WRITE
  268.   MOV BX,1          ; handle number for standard output is 1
  269.   INT 33          ; call MS-DOS to make the output
  270.   POP DX,CX,BX          ; restore clobbered registers
  271.   RET
  272.  
  273.  
  274.  
  275. NOW_BELL:
  276.   DB 'Now we''re using BIOS to ring the bell...',0D,0A,0
  277. HEAR_IT?:
  278.   DB 'Did you hear it?',0D,0A,0
  279.  
  280. TEST_KEY_BELL:        ; take 4 test keystrokes
  281.   CALL KEY_ONLY     ; take key without bell
  282.   CALL KEY_ONLY     ; take second key, without bell
  283.   CALL KEY_BELL     ; take a key then ring the bell
  284. KEY_BELL:        ; prompt for key, then ring the bell
  285.   CALL KEY_ONLY     ; prompt for and take a keystroke
  286.   MOV SI,NOW_BELL    ; point to bell message
  287.   CALL MESSAGE        ; put out the bell message
  288.   CALL BIOS_BELL    ; ring the bell
  289.   MOV SI,HEAR_IT?    ; point to the post-bell message
  290.   JMP MESSAGE        ; output the post-bell message
  291.  
  292.  
  293.  
  294. ; REFRESH updates the console screen to the desired contents, as indicated by
  295. ;   the SCRBASE buffer.  The buffer is updated to show that the actual screen
  296. ;   contents matches the desired contents.
  297.  
  298. REFRESH:
  299.   PUSH BX,CX,DX,BP,SI,DI,ES,DS ; preserve all registers but AX
  300.   MOV ES,VIDEO_SEG           ; we will copy to the screen-segment
  301.   MOV AH,NORM_ATTR      ; characters will have the normal attribute
  302.   MOV SI,SCREEN_P      ; source pointer is our screen buffer
  303.   SUB DI,DI          ; offset of the screen is zero
  304.   MOV BL,24          ; BL will count down lines
  305.   MOV CH,0          ; CX will always hold byte counts
  306. L1:              ; main loop for actual vs. desired comparison
  307.   MOV CL,80          ; count number of characters in a line
  308.   CALL VID_COPY       ; copy this line to the video buffer
  309.   OR SI,0FF          ; advance SI to the end of this buffer-page
  310.   INC SI          ; bump SI to the beginning of the next page
  311.   DEC BL          ; count down lines
  312.   JNZ L1          ; loop if there are more lines
  313.   POP DS,ES,DI,SI,BP,DX,CX,BX    ; restore all the registers
  314.   RET
  315.  
  316.  
  317.  
  318. ; This section of code defines the message-displays for the control keys.
  319.  
  320. MSG MACRO
  321. #1_MSG:
  322.   DB '#1',0
  323. #EM
  324.  
  325. MSG F1
  326. MSG F2
  327. MSG F3
  328. MSG F4
  329. MSG F5
  330. MSG F6
  331. MSG F7
  332. MSG F10
  333. MSG DOWN
  334. MSG PGDN
  335. MSG UP
  336. MSG HOME
  337. MSG SHF7
  338. MSG ALTF9
  339.  
  340. ; HEX_AL outputs to DI-pointed memory the 2-digit hex number representing
  341. ;   the value of AL.
  342.  
  343. BINHEX_AL  MACRO
  344.   ADD AL,090H        ; these 4 lines convert AL into an ASCII hex digit,
  345.   DAA            ;     in an outrageously clever and incomprehensible
  346.   ADC AL,040H        ;     fashion!!!  (I got the 8080 version of this out
  347.   DAA            ;     of an early BYTE magazine.)
  348. #EM
  349.  
  350. HEX_AL:
  351.   AAM 16        ; unpack AL into nibbles AH and AL
  352.   CALL >L3        ; swap nibbles, then output new low nibble
  353. L3:            ; call here to output nibble AH
  354.   XCHG AL,AH        ; swap the nibble into AL
  355.   BINHEX_AL        ; convert AL to a hex digit
  356.   STOSB         ; output the digit
  357.   RET
  358.  
  359.  
  360.  
  361. FIRST_FILL:          ; fill the video screen with its first contents
  362.   MOV DI,SCREEN_P      ; point to our screen image
  363.   MOV CX,(24 BY 0)/2      ; load the number of words in the image buffer
  364.   SUB AX,AX          ; we will zero-fill the buffer
  365.   REP STOSW          ; buffer is initialized to all-zeroes
  366.   MOV AL,' '              ; now load a blank
  367.   CALL FILL_LINES      ; fill the character line-buffers with blanks
  368.   CALL VID_FIX          ; insure that this first screen was actually sent
  369.   CALL REFRESH          ; send our screen buffer to video memory
  370.   RET
  371.  
  372.  
  373.  
  374. ALPHA_LINES:          ; put alphabet A to X down the left side
  375.   MOV DI,SCREEN_P      ; point to the upper left corner
  376.   MOV CX,24          ; load the lines count
  377.   MOV AL,'A'              ; load the first letter
  378. L1:              ; loop here to output each letter
  379.   STOSB           ; output the letter
  380.   INC AX          ; increment to the next letter
  381.   ADD DI,255          ; advance output pointer to the next line
  382.   LOOP L1          ; loop to output the next letter
  383.   RET
  384.  
  385.  
  386.  
  387. FILL_LINES:          ; fill all 24 image-lines with AL
  388.   MOV DI,SCREEN_P      ; point to the start of the image-buffer
  389.   MOV BL,24          ; number of lines in the buffer
  390. L1:              ; loop here for each line
  391.   CALL FILL_LINE      ; fill the line with AL
  392.   DEC BL          ; count down lines
  393.   JNZ L1          ; loop to fill the next line
  394.   RET
  395.  
  396.  
  397.  
  398. FILL_LINE:          ; fill the DI-pointed line with AL, advance DI
  399.   MOV CX,80          ; number of characters in the line
  400.   REP STOSB          ; fill the line
  401.   ADD DI,256-80       ; advance output pointer to the next line buffer
  402.   RET
  403.  
  404.  
  405.  
  406. PRESS_KEY:
  407.   DB '   Press any key',0
  408.  
  409. TOP_LINE:                 ; put SI-message and "press key" on top line
  410.   MOV DI,SCREEN_P+3      ; point to the fourth character of the top line
  411.   CALL COPY_STRING        ; output the caller's SI-pointed message
  412.   MOV SI,PRESS_KEY        ; now point to our "press key" message
  413. COPY_LINE:
  414.   CALL COPY_STRING        ; output the "press key" message
  415.   MOV CX,DI          ; copy the beyond-output pointer to CX
  416.   MOV CL,80          ; advance the pointer to the end of the top line
  417.   SUB CX,DI          ; calculate the number of trailing bytes in the line
  418.   MOV AL,' '              ; load blank
  419.   REP STOSB          ; blank-fill the trailing bytes
  420.   RET
  421.  
  422.  
  423.  
  424. ALL_KEYS:
  425.   DB 'Now try out all possible keystrokes.',0
  426. CAP_Q:
  427.   DB 'Capital Q exits program; capital T trashes the screen.',0
  428. TRASH_MESSAGE:
  429.   DB 'The message is output via MS_DOS.',0D,0A
  430.   DB 'It will roll the screen, thereby trashing the display.',0D,0A
  431.   DB 'Type capital-F to fix the screen if it is trashed.',0D,0A,0
  432. KNOWN_MSG:
  433.   DB 'I recognize that function key, its name is '
  434. KNOWN_TAIL:
  435.   DB '               ',0
  436. UNKNOWN_MSG:
  437.   DB 'That key code is not in my table.  Its value is '
  438. UNKNOWN_HEXCODE:
  439.   DB 'xx',0
  440. DISPLAYING_MSG:
  441.   DB 'Displayable character was typed: the character is "'
  442. DISPLAYING_CHAR DB 'x"',0
  443.  
  444. TEST_KEY_CODES:       ; interactive routine for displaying key codes
  445.   MOV SI,ALL_KEYS      ; point to the main prompting message
  446.   MOV DI,SCREEN_P+3      ; point to the location in our buffer for message
  447.   CALL COPY_LINE      ; output the first line of the message
  448.   MOV SI,CAP_Q          ; point to second line of message
  449.   MOV DI,SCREEN_P+0103      ; point to location in buffer for that message
  450.   CALL COPY_LINE      ; output the second line
  451. L1:              ; loop here for each keystroke
  452.   CALL REFRESH          ; refresh the video screen
  453.   CALL GET_KEY          ; take a keystroke
  454.   CMP AL,'Q'              ; is it the exiting capital-Q?
  455.   JE RET          ; if yes then exit
  456.   CMP AL,'T'              ; is it the TRASH command?
  457.   JE >L6          ; jump if yes
  458.   CMP AL,'F'              ; is it the FIX command?
  459.   JE >L7          ; jump if yes
  460.   MOV BL,AL          ; copy character to BL for WAVY-function
  461.   CMP AL,' '              ; is the character a control character?
  462.   JB >L5          ; jump if yes
  463.   CMP AL,07E          ; is the character above the displaying range?
  464.   JA >L5          ; jump if yes
  465.   MOV DISPLAYING_CHAR,AL  ; character is displayable-- put it into message
  466.   MOV SI,DISPLAYING_MSG   ; point to the displayable message
  467.   JMP >L4          ; jump to propagate the message
  468.  
  469. L5:              ; keystroke is not a displayable character
  470.   MOV DI,CTRL_JUMPS+2      ; point to our table of function keys
  471. L2:              ; loop here to search each entry of function table
  472.   CMP B[DI],0FF       ; is the table exhausted?
  473.   JE >L3          ; jump if yes, key not in table
  474.   SCASB           ; does our key match the table entry?
  475.   LEA DI,[DI+2]       ; advance table pointer in case not
  476.   JNE L2          ; loop if not
  477.   MOV SI,[DI-5]       ; the key matches-- fetch the pointer from that record
  478.   MOV DI,KNOWN_TAIL      ; point to the end of the known-message
  479.   CALL COPY_STRING        ; tack the key's name onto the known-message
  480.   MOV AL,0          ; load terminator
  481.   STOSB           ; null-terminate the known-message
  482.   MOV SI,KNOWN_MSG      ; point to the start of the known-message
  483.   JMP >L4          ; jump to propagate the message
  484.  
  485. L3:              ; keystroke was not found in the function table
  486.   MOV DI,UNKNOWN_HEXCODE  ; point to hex-display part of unknown-message
  487.   CALL HEX_AL          ; output our keycode as hex digits
  488.   MOV SI,UNKNOWN_MSG      ; point to the start of the unknown message
  489. L4:              ; common output point
  490.   CALL WAVY_MESSAGES      ; output the SI-pointed message in a wavy display
  491.   JMP L1          ; loop to take another keystroke
  492.  
  493. L6:              ; capital T is seen
  494.   MOV SI,TRASH_MESSAGE      ; point to our message that trashes the screen
  495.   CALL MESSAGE          ; trash the screen with the message
  496.   CALL BIOS_SAVE
  497.   JMP L1          ; loop to take another keystroke
  498.  
  499. L7:              ; capital F is seen
  500.   CALL VID_FIX          ; fix up the trashed screen
  501.   JMP L1          ; loop to take another keystroke
  502.  
  503.  
  504.  
  505. COPY_STRING:          ; copy SI-pointed string to DI
  506.   LODSB           ; load the first character
  507. L1:              ; loop here for each nonzero character
  508.   STOSB           ; output the character
  509.   LODSB           ; fetch the next character
  510.   TEST AL          ; is it the terminating zero?
  511.   JNZ L1          ; loop if not
  512.   RET
  513.  
  514.  
  515. WAVY   DB  3,4,5,6,7,6,5,4
  516.  
  517. WAVY_MESSAGES:          ; make 20 copies of SI-message in a wavy pattern
  518.   INC WAVY_COUNT      ; increment display count
  519.   MOV DI,SCREEN_P+0404      ; point to the first line of the wavy display
  520.   MOV BH,20          ; load the count of lines to be output
  521. L1:              ; loop here to output each line
  522.   MOV CX,DI          ; fetch the output pointer
  523.   MOV CL,CH          ; low byte tells us a reltive line number
  524.   ADD CL,BL          ; add in character code, just to mix things up
  525.   SUB CL,WAVY_COUNT      ; now a repeat of same key will make waves
  526.   AND CX,7          ; waviness will have a period of 8 lines
  527.   XCHG BX,CX          ; swap the line-index into BX, for addressing
  528.   MOV BL,WAVY[BX]      ; translate line-index into an indetation count
  529.   XCHG CX,BX          ; swap the count back into CX
  530.   MOV AL,' '              ; load blank
  531.   REP STOSB          ; indent the message-- this creates the waviness
  532.   PUSH SI          ; save the message pointer for the next line
  533.   CALL COPY_LINE      ; copy the message to this line, with trailing blanks
  534.   POP SI          ; restore the message pointer
  535.   ADD DI,260-80       ; advance output to the next line
  536.   DEC BH          ; count down lines
  537.   JNZ L1          ; loop to output the next line
  538.   RET
  539.